home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ETO Development Tools 4
/
ETO Development Tools 4.iso
/
Tools - Objects
/
Virtual User 1.0
/
Example Scripts
/
TowersOfHanoi.vu
< prev
Wrap
Text File
|
1991-01-25
|
8KB
|
246 lines
#
# File: TowersOfHanoi.vu
#
# Contains: The script solves the problem of Towers of Hanoi.
# To be able to run this script, the target should be in
# Finder, with either a window open or a volume selected.
#
# To Run this script set the following variables towards the end
# of this file: (default values in parens)
# Total_disks(3) : the number of disks you want the towers to be
# built with.
# From_tower(1) : the tower from which you want to move;
# To_tower(3) : the tower to which you want to move;
# Using_tower(2): the tower which will be used as a temporary one
#
# Prerequisite: This script makes use of the tasks library UtilityTasksLib.vu
# Make sure this library is put into the Libraries folder of your
# Virtual User folder.
#
# Warning: This script will create a set of folders in the open/selected
# volume. So do trash these folders after the script completes
# its execution. Also, if the folders with the names used already
# exist (from previous execution) the script will not work.
#
#
# Written by: P Nagarajan
#
# Copyright: © 1989 by Apple Computer, Inc., all rights reserved.
#
# Change History:
#
# 3/29/89 naga Creation
#
#
# To Do:
#
Libraries "UtilityTasksLib.vu";
task add_move(from_t, to_t, all_moves)
#adds a move of the form {from_t, to_t} to the global list 'all_moves'.
# all Arguments should be integers
begin
all_moves := all_moves + {{from_t, to_t}};
return all_moves;
end;
task gen_moves(from_t, to_t, using, num_disks, all_moves)
#generates moves for moving 'num_disks' number of disks from 'from_t' tower
#to 'to_t' tower using 'using' tower
# all Arguments should be integers
begin
if not (num_disks = 0) do
begin
if (num_disks = 1) do
return add_move(from_t, to_t, all_moves);
else do
begin
all_moves := gen_moves(from_t, using, to_t, num_disks - 1, all_moves);
all_moves := add_move(from_t, to_t, all_moves);
all_moves := gen_moves(using, to_t, from_t, num_disks - 1, all_moves);
return all_moves;
end;
end;
end; #task gen_moves
task set_up_tower(tower, no_of_disks)
#sets up the tower called Tower{tower} made of 'no_of_disks'
#Prereqs:: 'Base_dimension' : an integer specifying the size of the base disk(window)
# 'Position_of_tower' : a list having the initial position of each tower,
# position being {x, y}.
#Results:: 'Delta_for_tower' : sets up this global list, which gives the displacement of the topmost
# disk from the base, on each tower. ( a list of 3 integers).
# 'success' : if setup successful returns true else false.
begin
global Screen_rect;
global Base_dimension;
global Position_of_tower;
j := tower; #tower number
i := no_of_disks;
if (OpenOneWindow()) do
begin
Drag [Window] a: {Screen_rect[3]-12, Screen_rect[4]-50};
Select [MenuItem t: 'New Folder' m:'File'];
Type k:{"Tower{j}"};
Select [MenuItem t:'Open' m:'File'];
Drag [Window t:"Tower{j}"] a: {1,20};
Size [Window t:"Tower{j}"] h: Base_dimension w:Base_dimension;
Drag [Window t:"Tower{j}"] a: {Screen_rect[3]-12, Screen_rect[4]-50};
global Delta_for_tower := {0,0,0};
delta_move := Delta_for_tower[j];
while (i > 0) do
begin
Select [Window t:"Tower{j}"];
Select [MenuItem t: 'New Folder' m:'File'];
Type k:{"Disk{i}"};
Select [MenuItem t:'Open' m:'File'];
new_position := {(Position_of_tower[j][1] + delta_move),
(Position_of_tower[j][2] - delta_move) };
if not (match[window t: "Disk{i}"]!)
begin
println "couldn't find window: Disk{i}: ", i;
exit;
end;
Drag [Window t:"Disk{i}"] a: {1,20};
Size [Window t:"Disk{i}"] h:Base_dimension - delta_move/2 w:Base_dimension - 2*delta_move;
Drag [Window t:"Disk{i}"] a: new_position;
delta_move := delta_move + 5;
i := i - 1;
end;
Delta_for_tower := replace((delta_move - 5), j, Delta_for_tower);
success := true;
end; #if one window opened successfully
else do
begin
success := false;
end; #could not open a single window
return success;
end; #task set_up_tower
task make_moves(all_moves)
#this task actually makes the moves (dragging windows) using the moves,
#stored in the argument 'all_moves'.
#Prereqs :: 'all_moves' a list containing moves of form {i,j}
# 'Position_of_tower' : a list having the initial position of each tower,
# position being {x, y}.
# 'Delta_for_tower' : a list which gives the displacement for the next disk
# to be placed on a tower (from the original position of the tower).
begin
global Delta_for_tower;
global Position_of_tower;
x := 1; #index to get x-coord
y := 2; #index to get y-coord
for each disk_move in all_moves do
begin
i := disk_move[1] ;
j := disk_move[2] ; #move from tower i to tower j
delta_move := Delta_for_tower[j] + 5;
newx := Position_of_tower[j][x] + delta_move;
newy := Position_of_tower[j][y] - delta_move;
new_position := {newx, newy};
wind_rect := {Position_of_tower[i][x] + Delta_for_tower[i], #left
Position_of_tower[i][y] - Delta_for_tower[i], #top
0 ,#right
0 #bottom
};
Select [Window t:?selected_title r:wind_rect];
match [Window t:?drag_title o:1];
if selected_title <> drag_title
begin
println "looking for window: ", selected_title;
println "found window: ", drag_title;
exit;
end;
Drag [Window t:drag_title o:1] a: new_position;
Delta_for_tower := update_Delta_for_tower(delta_move, i, j, Delta_for_tower);
end; #for_each move
end; #task make_moves
task update_Delta_for_tower(delta_move, from_t, to_t, Delta_for_tower)
begin
if (Delta_for_tower[from_t] <> 0) do
Delta_for_tower := replace((Delta_for_tower[from_t] - 5), from_t, Delta_for_tower);
Delta_for_tower := replace(delta_move, to_t, Delta_for_tower);
return Delta_for_tower;
end; #task update_Delta_for_tower
task find_screen_dimensions()
begin
global Screen_rect, Screen_width, Screen_height;
match[screen r:?Screen_rect m:true];
Screen_width := Screen_rect[3]- Screen_rect[1];
Screen_height := Screen_rect[4]- Screen_rect[2];
end; #find_screen_dimensions
task check_for_max_tower_size(total_disks)
begin
global Screen_width, Screen_height;
max_disks1 := ((Screen_height - 20) - 112)/5;
max_disks2 := (((Screen_width - 30)/3) - 112)/5;
if max_disks2 >= max_disks1 #find the tighter of the two bounds
begin
max_tower_size := max_disks1;
end;#if
else
begin
max_tower_size := max_disks2;
end;#if
if total_disks > max_tower_size
begin
println "Sorry can draw only tower with a maximum of ", max_tower_size,
" disks on this target's main screen.";
println "Try with lesser number of disks or a larger screen!";
exit;
end;#if
return true;
end; #check_for_max_tower_size
task set_tower_dimensions_and_position(total_disks)
begin
global Base_dimension, Position_of_tower, Screen_rect, Screen_width, Screen_height;
Base_dimension := 117 + 5*(total_disks - 1);
x_offset := (Screen_width-Base_dimension*3)/4;
y_offset := (Screen_height-Base_dimension)/2;
Position_of_tower := {{(Screen_rect[1] + x_offset),(Screen_rect[2] + y_offset)},
{(Screen_rect[1] + x_offset*2 + Base_dimension), (Screen_rect[2] + y_offset)},
{(Screen_rect[1] + x_offset*3 + Base_dimension*2), (Screen_rect[2] + y_offset)}};
end;# set_tower_dimensions_and_position
All_moves := {};
From_tower := 1;
To_tower := 3;
Using_tower := 2;
Total_disks := 3;
System7 := RunningSystemSeven();;
if (System7) # 7.0.x system software on target
begin
Patience(6);
end; #if System7
find_screen_dimensions();
if (check_for_max_tower_size(Total_disks))
begin
set_tower_dimensions_and_position(Total_disks);
println "Now computing the moves...";
All_moves := gen_moves(From_tower, To_tower, Using_tower, Total_disks, All_moves);
println "done!";
println "Now setting up the tower of disks...";
success := set_up_tower(From_tower, Total_disks);
if (success) do
begin
println "done!";
println "Now making the moves...";
make_moves(All_moves);
println "done!";
end;
else do
println "Target not set up to solve the problem. Sorry.";
end;#if Total_disks permissible